Introduction des données

On voit que les deux premières colonnes (X & id) sont inutiles pour nos analyses, on va donc les supprimer

data <- read.csv("data/train.csv") 
str(data)
## 'data.frame':    103904 obs. of  25 variables:
##  $ X                                : int  0 1 2 3 4 5 6 7 8 9 ...
##  $ id                               : int  70172 5047 110028 24026 119299 111157 82113 96462 79485 65725 ...
##  $ Gender                           : chr  "Male" "Male" "Female" "Female" ...
##  $ Customer.Type                    : chr  "Loyal Customer" "disloyal Customer" "Loyal Customer" "Loyal Customer" ...
##  $ Age                              : int  13 25 26 25 61 26 47 52 41 20 ...
##  $ Type.of.Travel                   : chr  "Personal Travel" "Business travel" "Business travel" "Business travel" ...
##  $ Class                            : chr  "Eco Plus" "Business" "Business" "Business" ...
##  $ Flight.Distance                  : int  460 235 1142 562 214 1180 1276 2035 853 1061 ...
##  $ Inflight.wifi.service            : int  3 3 2 2 3 3 2 4 1 3 ...
##  $ Departure.Arrival.time.convenient: int  4 2 2 5 3 4 4 3 2 3 ...
##  $ Ease.of.Online.booking           : int  3 3 2 5 3 2 2 4 2 3 ...
##  $ Gate.location                    : int  1 3 2 5 3 1 3 4 2 4 ...
##  $ Food.and.drink                   : int  5 1 5 2 4 1 2 5 4 2 ...
##  $ Online.boarding                  : int  3 3 5 2 5 2 2 5 3 3 ...
##  $ Seat.comfort                     : int  5 1 5 2 5 1 2 5 3 3 ...
##  $ Inflight.entertainment           : int  5 1 5 2 3 1 2 5 1 2 ...
##  $ On.board.service                 : int  4 1 4 2 3 3 3 5 1 2 ...
##  $ Leg.room.service                 : int  3 5 3 5 4 4 3 5 2 3 ...
##  $ Baggage.handling                 : int  4 3 4 3 4 4 4 5 1 4 ...
##  $ Checkin.service                  : int  4 1 4 1 3 4 3 4 4 4 ...
##  $ Inflight.service                 : int  5 4 4 4 3 4 5 5 1 3 ...
##  $ Cleanliness                      : int  5 1 5 2 3 1 2 4 2 2 ...
##  $ Departure.Delay.in.Minutes       : int  25 1 0 11 0 0 9 4 0 0 ...
##  $ Arrival.Delay.in.Minutes         : num  18 6 0 9 0 0 23 0 0 0 ...
##  $ satisfaction                     : chr  "neutral or dissatisfied" "neutral or dissatisfied" "satisfied" "neutral or dissatisfied" ...
# On retire les colonnes inutiles
data <- data[,c(-1,-2)]
# On modifie les noms des colonnes pour le style ;-)
row.names(data) <- paste("n°", sep="", 1:dim(data)[1]) 
# On renomme les colonnes pour avoir des noms moins longs (Utile pour l'affichage)
colnames(data) <- c("Genre", "Fidélité", "Age", "Type.du.vol", "Classe", "Distance", "Wifi", "Horaire.pratique", "Facilité.resevation", "Emplacement.porte", "Nourriture", "Enregistrement.en.ligne", "Siege.confort", "Loisir", "On.board.service", "Espace.jambe", "Gestion.bagage", "Checkin.service", "Inflight.service", "Propreté", "Retard.depart", "Retard.arrivé", "Satisfaction")
str(data)
## 'data.frame':    103904 obs. of  23 variables:
##  $ Genre                  : chr  "Male" "Male" "Female" "Female" ...
##  $ Fidélité               : chr  "Loyal Customer" "disloyal Customer" "Loyal Customer" "Loyal Customer" ...
##  $ Age                    : int  13 25 26 25 61 26 47 52 41 20 ...
##  $ Type.du.vol            : chr  "Personal Travel" "Business travel" "Business travel" "Business travel" ...
##  $ Classe                 : chr  "Eco Plus" "Business" "Business" "Business" ...
##  $ Distance               : int  460 235 1142 562 214 1180 1276 2035 853 1061 ...
##  $ Wifi                   : int  3 3 2 2 3 3 2 4 1 3 ...
##  $ Horaire.pratique       : int  4 2 2 5 3 4 4 3 2 3 ...
##  $ Facilité.resevation    : int  3 3 2 5 3 2 2 4 2 3 ...
##  $ Emplacement.porte      : int  1 3 2 5 3 1 3 4 2 4 ...
##  $ Nourriture             : int  5 1 5 2 4 1 2 5 4 2 ...
##  $ Enregistrement.en.ligne: int  3 3 5 2 5 2 2 5 3 3 ...
##  $ Siege.confort          : int  5 1 5 2 5 1 2 5 3 3 ...
##  $ Loisir                 : int  5 1 5 2 3 1 2 5 1 2 ...
##  $ On.board.service       : int  4 1 4 2 3 3 3 5 1 2 ...
##  $ Espace.jambe           : int  3 5 3 5 4 4 3 5 2 3 ...
##  $ Gestion.bagage         : int  4 3 4 3 4 4 4 5 1 4 ...
##  $ Checkin.service        : int  4 1 4 1 3 4 3 4 4 4 ...
##  $ Inflight.service       : int  5 4 4 4 3 4 5 5 1 3 ...
##  $ Propreté               : int  5 1 5 2 3 1 2 4 2 2 ...
##  $ Retard.depart          : int  25 1 0 11 0 0 9 4 0 0 ...
##  $ Retard.arrivé          : num  18 6 0 9 0 0 23 0 0 0 ...
##  $ Satisfaction           : chr  "neutral or dissatisfied" "neutral or dissatisfied" "satisfied" "neutral or dissatisfied" ...

Petit avant gout des données :

paged_table(data)

Les notes sont assez homogènes, elles ont toutes :

summary(data)
##     Genre             Fidélité              Age        Type.du.vol       
##  Length:103904      Length:103904      Min.   : 7.00   Length:103904     
##  Class :character   Class :character   1st Qu.:27.00   Class :character  
##  Mode  :character   Mode  :character   Median :40.00   Mode  :character  
##                                        Mean   :39.38                     
##                                        3rd Qu.:51.00                     
##                                        Max.   :85.00                     
##                                                                          
##     Classe             Distance         Wifi      Horaire.pratique
##  Length:103904      Min.   :  31   Min.   :0.00   Min.   :0.00    
##  Class :character   1st Qu.: 414   1st Qu.:2.00   1st Qu.:2.00    
##  Mode  :character   Median : 843   Median :3.00   Median :3.00    
##                     Mean   :1189   Mean   :2.73   Mean   :3.06    
##                     3rd Qu.:1743   3rd Qu.:4.00   3rd Qu.:4.00    
##                     Max.   :4983   Max.   :5.00   Max.   :5.00    
##                                                                   
##  Facilité.resevation Emplacement.porte   Nourriture    Enregistrement.en.ligne
##  Min.   :0.000       Min.   :0.000     Min.   :0.000   Min.   :0.00           
##  1st Qu.:2.000       1st Qu.:2.000     1st Qu.:2.000   1st Qu.:2.00           
##  Median :3.000       Median :3.000     Median :3.000   Median :3.00           
##  Mean   :2.757       Mean   :2.977     Mean   :3.202   Mean   :3.25           
##  3rd Qu.:4.000       3rd Qu.:4.000     3rd Qu.:4.000   3rd Qu.:4.00           
##  Max.   :5.000       Max.   :5.000     Max.   :5.000   Max.   :5.00           
##                                                                               
##  Siege.confort       Loisir      On.board.service  Espace.jambe  
##  Min.   :0.000   Min.   :0.000   Min.   :0.000    Min.   :0.000  
##  1st Qu.:2.000   1st Qu.:2.000   1st Qu.:2.000    1st Qu.:2.000  
##  Median :4.000   Median :4.000   Median :4.000    Median :4.000  
##  Mean   :3.439   Mean   :3.358   Mean   :3.382    Mean   :3.351  
##  3rd Qu.:5.000   3rd Qu.:4.000   3rd Qu.:4.000    3rd Qu.:4.000  
##  Max.   :5.000   Max.   :5.000   Max.   :5.000    Max.   :5.000  
##                                                                  
##  Gestion.bagage  Checkin.service Inflight.service    Propreté    
##  Min.   :1.000   Min.   :0.000   Min.   :0.00     Min.   :0.000  
##  1st Qu.:3.000   1st Qu.:3.000   1st Qu.:3.00     1st Qu.:2.000  
##  Median :4.000   Median :3.000   Median :4.00     Median :3.000  
##  Mean   :3.632   Mean   :3.304   Mean   :3.64     Mean   :3.286  
##  3rd Qu.:5.000   3rd Qu.:4.000   3rd Qu.:5.00     3rd Qu.:4.000  
##  Max.   :5.000   Max.   :5.000   Max.   :5.00     Max.   :5.000  
##                                                                  
##  Retard.depart     Retard.arrivé     Satisfaction      
##  Min.   :   0.00   Min.   :   0.00   Length:103904     
##  1st Qu.:   0.00   1st Qu.:   0.00   Class :character  
##  Median :   0.00   Median :   0.00   Mode  :character  
##  Mean   :  14.82   Mean   :  15.18                     
##  3rd Qu.:  12.00   3rd Qu.:  13.00                     
##  Max.   :1592.00   Max.   :1584.00                     
##                    NA's   :310

Analyse des données

ACP

On récupère toutes les données quantitatives et la satisfaction.

On ne prend que les 5000 premières lignes car le data set est trop gros (+100 000 lignes)

# On récupère Âge/Distance du vol/Retard Depart/Retard Arrivé (colonne 3/6/21/22), les notes (colonnes 7 à 20) et la satisfaction (colonne 23)
data_bis <- data[1:5000,c(3,6,21,22,7:20,23)]
res <- PCA(data_bis, quanti.sup=1:4, quali.sup=19, graph=FALSE)
## Warning in PCA(data_bis, quanti.sup = 1:4, quali.sup = 19, graph = FALSE):
## Missing values are imputed by the mean of the variable: you should use the
## imputePCA function of the missMDA package

On revient sur nos données pour voir s’il n’y a pas eu de changement trop brutal :

summary(data_bis)
##       Age           Distance      Retard.depart    Retard.arrivé   
##  Min.   : 7.00   Min.   :  67.0   Min.   :  0.00   Min.   :  0.00  
##  1st Qu.:27.00   1st Qu.: 409.8   1st Qu.:  0.00   1st Qu.:  0.00  
##  Median :39.00   Median : 861.0   Median :  0.00   Median :  0.00  
##  Mean   :39.13   Mean   :1205.4   Mean   : 15.06   Mean   : 15.49  
##  3rd Qu.:51.00   3rd Qu.:1771.5   3rd Qu.: 14.00   3rd Qu.: 14.00  
##  Max.   :85.00   Max.   :4983.0   Max.   :480.00   Max.   :471.00  
##                                                    NA's   :13      
##       Wifi       Horaire.pratique Facilité.resevation Emplacement.porte
##  Min.   :0.000   Min.   :0.000    Min.   :0.000       Min.   :1.000    
##  1st Qu.:2.000   1st Qu.:2.000    1st Qu.:2.000       1st Qu.:2.000    
##  Median :3.000   Median :3.000    Median :3.000       Median :3.000    
##  Mean   :2.741   Mean   :3.033    Mean   :2.767       Mean   :2.972    
##  3rd Qu.:4.000   3rd Qu.:4.000    3rd Qu.:4.000       3rd Qu.:4.000    
##  Max.   :5.000   Max.   :5.000    Max.   :5.000       Max.   :5.000    
##                                                                        
##    Nourriture    Enregistrement.en.ligne Siege.confort       Loisir     
##  Min.   :0.000   Min.   :0.000           Min.   :1.000   Min.   :0.000  
##  1st Qu.:2.000   1st Qu.:2.000           1st Qu.:2.000   1st Qu.:2.000  
##  Median :3.000   Median :3.000           Median :4.000   Median :4.000  
##  Mean   :3.218   Mean   :3.253           Mean   :3.421   Mean   :3.339  
##  3rd Qu.:4.000   3rd Qu.:4.000           3rd Qu.:4.250   3rd Qu.:4.000  
##  Max.   :5.000   Max.   :5.000           Max.   :5.000   Max.   :5.000  
##                                                                         
##  On.board.service  Espace.jambe   Gestion.bagage  Checkin.service
##  Min.   :0.000    Min.   :0.000   Min.   :1.000   Min.   :1.000  
##  1st Qu.:2.000    1st Qu.:2.000   1st Qu.:3.000   1st Qu.:3.000  
##  Median :4.000    Median :4.000   Median :4.000   Median :3.000  
##  Mean   :3.361    Mean   :3.338   Mean   :3.623   Mean   :3.316  
##  3rd Qu.:4.000    3rd Qu.:4.000   3rd Qu.:5.000   3rd Qu.:4.000  
##  Max.   :5.000    Max.   :5.000   Max.   :5.000   Max.   :5.000  
##                                                                  
##  Inflight.service    Propreté     Satisfaction      
##  Min.   :0.000    Min.   :1.000   Length:5000       
##  1st Qu.:3.000    1st Qu.:2.000   Class :character  
##  Median :4.000    Median :3.000   Mode  :character  
##  Mean   :3.651    Mean   :3.268                     
##  3rd Qu.:5.000    3rd Qu.:4.000                     
##  Max.   :5.000    Max.   :5.000                     
## 

Les individus ou variables peuvent être proches dans le plan mais eloignés dans l’espace s’ils sont mal représentés dans le plan. Ainsi, il est important d’expliquer les individus avec des variables bien representées dans le plan. Pour cela on veillera à ne pas prendre les variables et individus ayant un cos2 trop bas. Ici on choisit un cos2 égale à 0.58 afin d’avoir au moins 4 variables à utiliser afin d’expliquer nos individus sur les axes 1 et 2.

Ici l’axe 1 va faire le contraste entre le confort à bord (droite) et l’inconfort (gauche), tandis que l’axe 2 fera le contraste entre les aspects techniques pour ce qui concerne le vol.

Les variables quantitatives supplémentaires ne sont pas du tout interprétables

plot(res,select="cos2 0.58", choix="varcor")

On peut voir une nette séparation entre les individus satisfaits et non satisfaits. Les individus satisfaits sont ceux s’étant amusé et ayant trouvé l’avion propre. À l’inverse les individus non satisfaits n’ont pas trouvé l’avion propre et ne se sont pas amusés. On ne peut pas vraiment dire pour l’instant si la facilité de réservation et le wifi à bord influent. Ici par exemple l’individu n°686 ne s’est pas amusé à bord et n’a pas non plus trouvé l’avion propre et il n’est pas satisfait.

plot(res,habillage=19, select="cos2 0.58", choix="ind")

L’individu qui contribue le plus à l’axe 1 : 0.15%.

Il y a 40 individus qui y contribuent pour plus de 0.1%

On n’a pas d’individus atypiques, ce qui est normal car nos données sont des notes entre 0 et 5 et on a vu qu’elles étaient assez homogènes

max(res$ind$contrib[,1])
## [1] 0.1527594
sum((res$ind$contrib[,1] > 0.1)*1)
## [1] 40

On peut voir premièrement que les 3 premiers axes expliquent bien l’inertie sur les données. Les axes étant orthogonaux, les axes 1 et 2 prennent en compte 26.99% + 16.90% = 43.89% du jeu de données expliquent 44.56% de l’inertie. On peut aussi voir que l’axe 2 et 3 expliquent à peu près autant l’un que l’autre l’inertie, ainsi on pourra aussi visualiser les données projetées sur le plan formé par l’axe 1 et 3 (même 2 et 3).

barplot(res$eig[,2], col=rainbow(n=14,alpha=0.6,start=0,end=0.33),main="Pourcentage d'inertie expliquée par chaque axe", ylab="Contribution en %")
lines(seq(0.75,16.3,(16.3-0.75)/13),res$eig[,2],type="b", xlim=c(0,max(res$eig[,2])+10))
text(seq(0.75,16.3,(16.3-0.75)/13),res$eig[,2]-1, paste(round(res$eig[,2],2),"%"), cex=0.7)

#text(5,22,paste(round(res$eig[,2],2)[1],"% +",round(res$eig[,2],2)[2],"% = ",round(res$eig[,2],2)[1]+round(res$eig[,2],2)[2],"%",sep=""))

On a un nouveau cercle de corrélation, ici on voit que :

  • Le confort des sièges, la nourriture et la propreté sont fortement corrélés
  • La gestion des bagages et les services proposés sont fortement corrélés
  • Dans ce plan les loisirs sont presque totalement expliqués par l’axe 1
  • L’axe 3 oppose le “confort” aux services qui sont faiblement corrélés dû à l’angle proche de 90 degrés
plot(res, select="cos2 0.58", choix="varcor", axes = c(1,3))

Les passagers sont en général plus satisfait quand ils se sont amusé et que le service était agréable.

plot(res, habillage=19, select="cos2 0.58", choix="ind", axes = c(1,3))

Ici on a le cercle de corrélation avec l’axe 2 et 3:

plot(res, select="cos2 0.6", choix="varcor", axes = c(2,3))

Il n’y a pas grand-chose à interpréter car le barycentre des voyageurs satisfaite et non satisfaits sont tout les 2 au centre de gravité de ce plan.

plot(res, choix="ind", axes = c(2,3))

Transformations & double centrage

Certains passagés ayant attribué comme notes 0 pour certaines catégories du vol on décide de ne pas faire de transformation par l’inverse car \(\frac{1}{0}\) est un quotient indéterminé

Log-transformation

On effectue la transformation ”double centrage” sur les données log-transformées afin de voir si on peut faire gagner en contribution les premières composantes afin d’être plus précis lors de nos analyses.

data_bis2 <- log(data_bis[,c(-4:-1,-19)])
data_bis2 <- t(scale(t(data_bis2)))
res2 <- PCA(data_bis2, graph=FALSE)
## Warning in PCA(data_bis2, graph = FALSE): Missing values are imputed by the mean
## of the variable: you should use the imputePCA function of the missMDA package
barplot(res2$eig[,2], col=rainbow(n=14,alpha=0.6,start=0.33,end=0.66),main="Pourcentage d'intertie expliquée par chaque axe\n(Données log-transformées) ", ylab="Contribution en %")
lines(seq(0.75,16.3,(16.3-0.75)/13),res2$eig[,2],type="b")
text(seq(0.75,16.3,(16.3-0.75)/13),res2$eig[,2]-1, paste(round(res2$eig[,2],2),"%"), cex=0.7)

Transformation par racines carrée

On effectue la transformation ”double centrage” sur les données transformées par racine carrée afin de voir si on peut faire gagner en contribution les premières composantes afin d’être plus précis lors de nos analyses.

data_bis3 <- sqrt(data_bis[,c(-4:-1,-19)])
data_bis3 <- t(scale(t(data_bis3)))
res3 <- PCA(data_bis3, graph=FALSE)
barplot(res3$eig[,2], col=rainbow(n=14,alpha=0.6,start=0.66,end=1),main="Pourcentage d'intertie expliquée par chaque axe\n(Données transformées par racine carrée)", ylab="Contribution en %")
lines(seq(0.75,16.3,(16.3-0.75)/13),res3$eig[,2],type="b")
text(seq(0.75,16.3,(16.3-0.75)/13),res3$eig[,2]-1, paste(round(res3$eig[,2],2),"%"), cex=0.7)

Les transformations ne nous ont pas fait gagner plus d’informations au niveau des 2 premiers axes, on s’arrête là pour l’ACP.

Conclusion ACP

Ici on a pu étudier l’impacte des variable quantitative sur la satisfaction des gens pour un trajet en avion. Il en est ressorti que les services proposés dans l’avion et le confort à bord sont un aspect primordial pour la satisfaction des voyageurs.